use std::env::temp_dir;
use std::fs::{self, remove_file, File, OpenOptions};
use std::io::{Read, Write};
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};

pub struct TempFile {
    file_path: PathBuf,
    file: File,
}

impl Drop for TempFile {
    fn drop(&mut self) {
        if fs::metadata(self.file_path.as_path()).is_ok() {
            let _ = remove_file(&self.file_path);
        }
    }
}

impl TempFile {
    pub fn new() -> Result<Self, std::io::Error> {
        // Your code here...
        let mut path_buf = temp_dir();
        path_buf.push(
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_nanos()
                .to_string(),
        );

        let f = File::create(path_buf.as_path())?;
        Ok(Self {
            file_path: path_buf,
            file: f,
        })
    }

    pub fn write(&self, data: &[u8]) -> Result<(), std::io::Error> {
        // Your code here...
        let mut file = OpenOptions::new().write(true).open(&self.file_path)?;
        file.write_all(data)?;
        Ok(())

        // let tmp = String::from("this is a test string.");
        // let u8 = b"this is a u8 array";
        // let u8_arr = tmp.as_bytes();
    }

    pub fn read_to_string(&self) -> Result<String, std::io::Error> {
        // Your code here...
        let mut file = OpenOptions::new().read(true).open(&self.file_path)?;
        let mut buffer = String::new();
        file.read_to_string(&mut buffer)?;
        Ok(buffer)
    }

    pub fn path(&self) -> &PathBuf {
        &self.file_path
    }

    pub fn file(&self) -> &File {
        &self.file
    }
}
